/**
 * 名字标签挂件：CGCR 2018 的底部文本滚动条
 * 
 * 注意: 因为是挂件, 所以没有 sendStatus 这个方法.
 * 该挂件的 Pendant 实例需要调用 sendStatus 方法, 因此需要上层设置 sendStatus 方法
 */

/**
 * public 创建 Pendant 挂件方法
 */
function createPendant(context) {
  let t = new CGCR2018Bottom(context);
  let p = new context.Pendant({
		require : ['zrender'],
		init : (libs, options) => t.init(libs, options),
		destroy : () => t.destroy(),
  });
  t.finished = () => p.finished();
  return p;
};

let zrender;

/**
 * 上层的 Scene 会注入 finished 方法.
 */
class CGCR2018Bottom {

  /** @type {number} 记录现在的状态号 */
  status = 0;
  /** @type {number} */
  intervalHandler = null;

  context = null;
  zr = null;

  vTitle = null;
  vText = null;

  layout = {
    /** 文本在屏幕上的宽度（像素） */
    vTitleRectWidth : 0,
    /** 文本在屏幕上的宽度（像素） */
    vTextRectWidth : 0,

    vArrawX : 0,

    canvasWidth : 0,
    canvasHeight : 0,
  };

  sprites = {
    pArrow : null,
    pTitle : null,
    pText : null,
  };

  props = {
    /** @type {string} */
    title : '这是一个标题',
    /** @type {string} */
    content : '想说啥呢',
    /** @type {number} 持续时间. 如果为 0 表示自适应 */
    duration : 0,

    el : 'main',
  };


  constructor(context) {
    this.context = context;
  };

  init (libs, args) {
    if (args) {
      Object.assign(this.props, args);
    }

    zrender = libs.zrender;
    let zr = this.zr = zrender.init(document.getElementById(this.props.el));

    this.layout.canvasWidth = zr.getWidth();
    this.layout.canvasHeight = zr.getHeight();

    loadArrow();
    zr.add(this.sprites.pArrow = new Arrow({
      position : [5, 1],
      style : {
        opacity : 0,
        shadowColor : '#00000050',
        shadowBlur : 16,
        shadowOffsetX : 16,
        stroke: 'rgb(236,132,38)',
        fill: new zrender.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0.2,
            color: 'rgb(254,203,1)'
          },
          {
            offset: 0.8,
            color: 'rgb(253,177,2)'
          }
        ], false)
      },
      z: 100
    }));

    this.layout.vArrawX = 250;
    zr.add(this.sprites.pTitle = new zrender.Text({
      style: {
        text: this.props.title,
        textAlign: 'left',
        fontWeight: 'bold',
        textVerticalAlign: 'bottom',
        fontSize: 32,
        fontFamily: 'Microsoft YaHei UI',
        textFill: '#FFF',
        textStroke: 'rgb(255,127,39)',
        textStrokeWidth: 8,
        opacity: 0
      },
      position: [60, 48],
      z: 101
    }));

    zr.add(this.sprites.pText = new zrender.Text({
      style: {
        text: this.props.content,
        textAlign: 'left',
        textVerticalAlign: 'bottom',
        fontSize: 30,
        fontFamily: 'Microsoft YaHei UI',
        textFill: '#FFF',
        textShadowBlur: 0,
        textShadowColor: '#000',
        textShadowOffsetX: 2,
        textShadowOffsetY: 2,
        opacity: 0
      },
      position: [135, 46],
      z: 1
    }));

    this.status = 0;

    // 重置文本框大小
    this.layout.vTitleRectWidth = this.sprites.pTitle.getBoundingRect().width;
    this.layout.vTextRectWidth = this.sprites.pText.getBoundingRect().width;
    this.layout.vArrawX = 100 + this.layout.vTitleRectWidth;

    this.intervalHandler = setInterval(() => this.tick(), 1000 / 60); // 60fps
  };

  tick () {
    switch (this.status) {
    case 0: this.animate3S0(); break;
    // 1 在动画中
    case 2: this.status = 3; setTimeout(() => this.status = 4, 100); break;
    case 4: this.animate3S4(); break;
    // 5 在动画中
    case 6: this.status = 7; setTimeout(() => this.status = 8, 100); break;
    case 8: this.animate3S8(); break;

    case 100: this.animate3S100(); break;
    // 101 在动画中
    case 102: this.status = 103; setTimeout(() => this.status = 104, 1500);  break;
    case 104: this.finished(); break; // 该部分动画结束
    }
  };

  destroy () {
    clearInterval(this.intervalHandler);
  };

  /* ***********
   * 动画部分区 *
   *********** */

  animate3S0() {
    this.status = 1;
    const {pArrow} = this.sprites;

    // Logo 淡入出现
    pArrow.attr({
      position: [5, 1],
      style: { opacity: 0 }
    });

    pArrow.animate('style', false)
      .when(100, {opacity : 1  })
      .when(200, {opacity : 0.2})
      .when(300, {opacity : 1  })
      .when(400, {opacity : 0.2})
      .when(500, {opacity : 1  })
      .done(() => this.status = 2)
      .start();
  };

  animate3S4() {
    this.status = 5;

    this.sprites.pArrow.animate('position', false)
      .when(1000, [5 + this.layout.vArrawX, 1])
      .done(() => this.status = 6)
      .start('cubicInOut');
  };

  animate3S8() {
    this.status = 9;
    const {pArrow, pTitle, pText} = this.sprites;
    const {vArrawX, canvasWidth, vTextRectWidth, vTitleRectWidth} = this.layout;

    // 左
    pArrow.animate('shape', false)
      .when(1000, {width: 112 + vArrawX})
      .start('cubicInOut');

    pArrow.animate('position', false)
      .when(1000, [-95, 1])
      .start('cubicInOut');

    pTitle.attr({
      style: {opacity: 0}
    });
    pTitle.animate('style', false)
      .delay(500)
      .when(1000, {opacity: 1})
      .start();

    // 右边
    pText.attr({
      style:{opacity:1},
      position:[canvasWidth, 46]
    });
    let width = vTextRectWidth + canvasWidth + 100 - vTitleRectWidth;
    let duration = this.props.duration;
    if (duration == 0 || isNaN(duration)) {
      duration = width * 6;
    }
    pText.animate('position', false)
      .when(duration, [-vTextRectWidth + vTitleRectWidth, 46])
      .done(() => {
        this.status = 100;
        pText.attr({style:{opacity:0}});
      })
      .start();
  };

  animate3S100() {
    this.status = 101;
    const {pArrow, pTitle} = this.sprites;

    pArrow.animate('shape', false)
      .delay(300)
      .when(500, {width: 12})
      .done(() => this.status = 102)
      .start('cubicIn');

    pTitle.animate('style', false)
      .when(500, {opacity: 0})
      .start();
  };
};

let Arrow;

function loadArrow() {
  if (Arrow != null) {
    return;
  }
  Arrow = zrender.Path.extend({
    type: 'arrow',
    shape: {
      // x, y on the cusp
      x: 0,
      y: 0,
      width: 12, // 默认值 ?
      height: 65, // 默认值 ?
      offset: 21
    },
    buildPath: function (path, shape) {
      var x = shape.x;
      var y = shape.y;

      var w = shape.width;
      var h = shape.height;
      var offset = shape.offset;

      path.lineTo(x, y);
      path.lineTo(x + offset, y + h / 2);
      path.lineTo(x, y + h);
      path.lineTo(x + w, y + h);
      path.lineTo(x + offset + w, y + h / 2);
      path.lineTo(x + w, y);
      path.lineTo(x, y);
      path.closePath();
    },
    style: {
      stroke: 'rgb(236,132,38)',
      lineWidth: 2,
      fill: new zrender.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0.2,
          color: 'rgb(254,203,1)'
        },
        {
          offset: 0.8,
          color: 'rgb(253,177,2)'
        }
      ], false)
    }
  });
}

// 对外开放哪些方法
export default createPendant;
